#include "tim3.h"

/************************************************************************
*函数名：TIM5_CH_Init
*函数功能：TIM5通道初始化配置函数
*函数参数：无
*函数返回值：无
*函数说明：TIM5_CH1——PA0——复用功能AF2
*************************************************************************/
void TIM5_CH_Init(void)
{
	/*使能GPIOA时钟*/
	RCC->AHB1ENR |= (1<<0);//使能GPIOA时钟

	/*配置GPIO控制器*/
	//模式寄存器——复用功能模式 10
	GPIOA->MODER &= ~	(3<<0*2);
	GPIOA->MODER |= 		(2<<0*2);

	//输出类型寄存器——推挽 0
	GPIOA->OTYPER &= ~(1<<0);

	//输出速度寄存器——低速 00
	GPIOA->OSPEEDR &= ~(3<<0*2);

	//上拉/下拉寄存器——无上下拉 00
	GPIOA->PUPDR &= ~(3<<0*2);

	//复用功能低位寄存器——AF2
	GPIOA->AFR[0] &= ~	(0xf<<0*4);
	GPIOA->AFR[0] |= 	(2<<0*4);
}


/************************************************************************
*函数名：TIM5_Init
*函数功能：TIM5初始化配置函数
*函数参数：无
*函数返回值：无
*函数说明：1ms进一次中断
*************************************************************************/
void TIM5_Init(void)
{
	/*TIM5通道初始化配置*/
	TIM5_CH_Init();

	/*使能TIM5时钟*/
	RCC->APB1ENR |= (1<<3);

	/*配置TIM5时基单元*/
	TIM5->CNT = 0;//计数器清零
	TIM5->PSC = 84-1;//分频84
	TIM5->ARR = 1000-1;//重装载值1000（1ms更新一次）

	/*配置TIM5寄存器*/
	TIM5->CR1 |= (1<<7);//ARR寄存器进行缓冲
	TIM5->CR1 &= ~(1<<3);//计数器更新后不会停止，而是重新开始计数
	TIM5->CR1 &= ~(1<<2);//UEV源：上溢/下溢，UG位置1等
	TIM5->CR1 &= ~(1<<1);//使能更新事件

	/*软件更新（可选）*/
	TIM5->EGR |= (1<<0);//UG位置1，手动更新
	TIM5->SR &= ~(1<<0);//清零中断标志位

	/*CC1输出比较配置*/
//	TIM3->CCMR1 &= ~(0xff<<0*8);//清零0-7位
//	TIM3->CCMR1 |= (7<<4);//PWM模式2：递增计数时，先输出无效电平，后输出有效电平 111
//	TIM3->CCER &= ~(0xf<<0*4);//清零0-3位（对应CC1通道）
//	TIM3->CCER |= (1<<0);//使能输出比较 1
//	TIM3->CCER |= (1<<1);//输出极性：低电平有效 1
//	TIM3->CCR1 = 10;//CC1输出比较值

	/*CC1输入捕获配置*/
	TIM5->CCMR1 &= ~(0xff<<0*8);//清零0-7位
	TIM5->CCMR1 |= (1<<0*2);//定义CC1通道方向为输入，IC1→TI1
	TIM5->CCER |= (1<<3|1<<1);//捕获1输出极性：双边沿触发
	TIM5->CCER |= (1<<0);//使能输入捕获1

	/*开启TIM5中断*/
	//在DIER开启捕获1中断、更新中断
	TIM5->DIER |= (1<<1|1<<0);
	//设置中断优先级
	NVIC_SetPriority(TIM5_IRQn,NVIC_EncodePriority(7-2,2,3));//给TIM5设置优先级为(2,3)
	//使能中断源
	NVIC_EnableIRQ(TIM5_IRQn);

	/*打开计数器*/
	TIM5->CR1 |= (1<<0);
}


/************************************************************************
*函数名：TIM5_IRQHandler
*函数功能：TIM5中断服务函数
*函数参数：无
*函数返回值：无
*函数说明：
*************************************************************************/
#define diff_count ((count_DOWN-count_UP)*(TIM5->ARR+1)+CCR1_DOWN-CCR1_UP)

void TIM5_IRQHandler(void)
{
	static u32 count_UEV = 0;
	static u32 count_UP = 0,count_DOWN = 0;
	static u16 CCR1_UP = 0,CCR1_DOWN = 0;
	if (TIM5->SR & (1<<0))//如果是更新中断
	{
		TIM5->SR &= ~(1<<0);//清零中断标志位
		count_UEV++;
	}
	if (TIM5->SR & (1<<1))//如果是捕获/比较1中断
	{
		TIM5->CCR1;//读取CCR1，将SR的第1位清零

		printf("TIM5 captured:");
		if (GPIOA->IDR & (1<<0))//如果PA0输入高电平
		{
			printf("0 UP\n");
			CCR1_UP = TIM5->CCR1;
			count_UP = count_UEV;
			printf("CNT:%d\n",TIM5->CCR1);
			printf("count_UEV:%d\n",count_UEV);
		}
		else
		{
			printf("0 DOWN\n");
			CCR1_DOWN = TIM5->CCR1;
			count_DOWN = count_UEV;
			printf("CNT:%d\n",TIM5->CCR1);
			printf("count_UEV:%d\n",count_UEV);
			printf("\n");
			printf("diff count:%d\n",diff_count);
			printf("diff time:%.4f ms\n",diff_count/1000.0);
		}
	}
}
